#include "stdafx.h"
#include "proc.h"

namespace xm
{
	static int32_t handle_index( uint32_t handle, uint32_t max_index )
	{
		if( handle < 4 ) return -1;
		if( handle & 3 ) return -1;
		int32_t i = (handle - 4)>>2;
		if( i >= max_index ) return -1;
		return i;
	}

	uint32_t process_t::handle_alloc( kip_t obj, uint32_t acc )
	{
		if( !obj ) return NULL;

		if( obj->Class() <= KoHandlable ) 
			return NULL;

		for( size_t i = 0; i < MAX_HANDLES; ++ i )
		{
			handle_t & h = _handles[i];
			if( h.obj ) continue;
			
			h.acc = acc;
			h.obj = obj;

			return (i+1)<<2;
		}
		return NULL;
	}
	kip_t process_t::handle_query( uint32_t handle, uint32_t * acc )
	{
		int32_t hi = handle_index(handle, MAX_HANDLES);
		if( hi < 0 ) return NULL;
		if( acc ) *acc = _handles[hi].acc;
		return _handles[hi].obj;
	}
	long process_t::handle_access( uint32_t handle, uint32_t add, uint32_t del )
	{
		int32_t hi = handle_index(handle, MAX_HANDLES);
		if( hi < 0 ) return E_INVALIDARG;
		_handles[hi].acc &= ~del;
		_handles[hi].acc |= add;
		return S_OK;
	}
	long process_t::handle_close( uint32_t handle )
	{
		int32_t hi = handle_index(handle, MAX_HANDLES);
		if( hi < 0 ) return E_INVALIDARG;

		handle_t & h = _handles[hi];
		if( !h.obj ) return E_INVALIDARG;

		// call close force
		h.obj.dispose();

		return S_OK;
	}
	long process_t::handle_clear()
	{
		for( size_t i = 0; i < MAX_HANDLES; ++ i )
		{
			handle_t & h = _handles[i];			
			h.acc = 0;
			h.obj.dispose();
		}
		return S_OK;
	}
	long process_t::handle_enum( size_t idx, uint32_t * handles, size_t want, size_t * rest )
	{
		return E_FAIL;
	}
};